package edu.hit.crawler.io;

import java.io.DataInput;
import java.io.DataOutput;
import java.io.IOException;

import org.apache.hadoop.io.Writable;

import edu.hit.crawler.util.MetaParser;

/**
 * Hadoop writable for storing web content and relative info.
 * 
 * @author Song Liu (Lamfeeling@126.com)
 * 
 */
public class DocumentWritable implements Writable {
	
	public static final int Crawled = 1, Uncrawled = 0;

	public static final float Intial_Score = 1.0f;
	
	private String document = new String();
	private String redirectedFrom = new String();
	private boolean metaFollow = true;
	//private boolean metaIndex = true;
	private int fail = 0;
	private String charset = "";

	private boolean crawledStatus = false;

	private float score = 1.0f;
	
	/**
	 * construct using document content and redirect source
	 * 
	 * @param doc
	 *            document conten
	 * @param red
	 *            document conten
	 */
	public DocumentWritable(String doc, String redirect, String charset, float score) {
		document = doc;
		redirectedFrom = redirect;
		// parse meta information
		MetaParser p = new MetaParser(doc);
		metaFollow = p.isFollowed();
		//metaIndex = p.isIndexed();
		this.charset = charset;
		this.score = score;
	}


	public DocumentWritable(String doc, String redirect, String charset, float score, boolean crawledStatus) {
		document = doc;
		redirectedFrom = redirect;
		// parse meta information
		MetaParser p = new MetaParser(doc);
		metaFollow = p.isFollowed();
		//metaIndex = p.isIndexed();
		this.charset = charset;
		this.score = score;
		this.crawledStatus = crawledStatus;
	}
	
	public DocumentWritable(float score, boolean crawledStatus) {
		this.score = score;
		this.crawledStatus = crawledStatus;
	}
	
	/*public DocumentWritable(boolean crawledStatus) {
		this.crawledStatus = crawledStatus;
	}*/
	
	public DocumentWritable(String url, float score, boolean crawledStatus) {
		this.redirectedFrom = url;
		this.score = score;
		this.crawledStatus = crawledStatus;
	}
	
	public void set(float score, boolean crawledStatus) {
		this.score = score;
		this.crawledStatus = crawledStatus;
	}
	
	public void set(String url, float score, boolean crawledStatus) {
		this.redirectedFrom = url;
		this.score = score;
		this.crawledStatus = crawledStatus;
	}
	
	/*public DocumentWritable(String url, boolean crawledStatus) {
		this.redirectedFrom = url;
		this.crawledStatus = crawledStatus;
	}*/

	/**
	 * construct the empty document content and redirect source and increase the
	 * number of retry
	 */
	public DocumentWritable() {
		fail++;
	}

	/**
	 * get the web content
	 * 
	 * @return
	 */
	public String getDocument() {
		return document;
	}

	/**
	 * get the redirect source of current URL
	 * 
	 * @return
	 */
	public String getRedirectedFrom() {
		return redirectedFrom;
	}

	/**
	 * get the times of retry
	 * 
	 * @return
	 */
	public int getFail() {
		return fail;
	}

	/**
	 * get meta value Follow
	 * 
	 * @return follow?
	 */
	public boolean isMetaFollow() {
		return metaFollow;
	}

	/**
	 * get meta value index
	 * 
	 * @return index?
	 */
	/*public boolean isMetaIndex() {
		return metaIndex;
	}*/

	public String getCharSet() {
		return charset;
	}

	public boolean getCrawledStatus() {
		return this.crawledStatus;
	}

	public void setCrawledStatus(boolean crawledStatus) {
		this.crawledStatus = crawledStatus;
	}
	
	public float getScore() {
		return score;
	}
	
	public void setScore(float score) {
		this.score = score;
	}

	/*
	 * @Override public void readFields(DataInput in) throws IOException { int
	 * len = in.readInt(); byte[] b = new byte[len]; in.readFully(b); document =
	 * new String(b, "utf-8"); redirectedFrom = in.readUTF(); fail =
	 * in.readInt(); metaFollow = in.readBoolean(); metaIndex =
	 * in.readBoolean(); len = in.readInt(); b = new byte[len]; in.readFully(b);
	 * charset = new String(b, "utf-8"); }
	 * 
	 * @Override public void write(DataOutput out) throws IOException { byte[] b
	 * = document.getBytes("utf-8"); out.writeInt(b.length); out.write(b);
	 * out.writeUTF(redirectedFrom); out.writeInt(fail);
	 * out.writeBoolean(metaFollow); out.writeBoolean(metaIndex); b =
	 * charset.getBytes("utf-8"); out.writeInt(b.length); out.write(b); }
	 */

	@Override
	public void readFields(DataInput in) throws IOException {

		// document = in.readUTF();

		int len = in.readInt();
		byte[] bytebuffer = new byte[len];
		in.readFully(bytebuffer);
		document = new String(bytebuffer, "utf-8");

		redirectedFrom = in.readUTF();
		fail = in.readInt();
		metaFollow = in.readBoolean();
		//metaIndex = in.readBoolean();
		charset = in.readUTF();
		score = in.readFloat();
		crawledStatus = in.readBoolean();
	}

	@Override
	public void write(DataOutput out) throws IOException {

		// out.writeUTF(document);
		
		byte[] bytebuffer = document.getBytes("utf-8");
		out.writeInt(bytebuffer.length);
		out.write(bytebuffer);

		out.writeUTF(redirectedFrom);
		out.writeInt(fail);
		out.writeBoolean(metaFollow);
		//out.writeBoolean(metaIndex);
		out.writeUTF(charset);
		out.writeFloat(score);
		out.writeBoolean(crawledStatus);
	}
}
